<!DOCTYPE html>
<html lang="en">

<head>
	<title>Multiple animated skinned meshes</title>
	<meta charset="utf-8">
	<meta content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" name="viewport">
	<link type="text/css" rel="stylesheet" href="main.css">
</head>

<body>
	<div id="info">
		This demo shows how to clone a skinned mesh using <strong>SkeletonUtils.clone()</strong><br />
		Soldier model from <a href="https://www.mixamo.com" target="_blank" rel="noopener">https://www.mixamo.com</a>.
	</div>

	<!-- Import maps polyfill -->
	<!-- Remove this when import maps will be widely supported -->
	<script async src="https://unpkg.com/es-module-shims@1.6.3/dist/es-module-shims.js"></script>

	<script type="importmap">
            {
              "imports": {
                "three": "../three.js-r151/build/three.module.js",
                "three/addons/": "../three.js-r151/examples/jsm/"
              }
            }
        </script>

	<script type="module">

		import * as THREE from 'three';

		import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
		import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

		import * as SkeletonUtils from 'three/addons/utils/SkeletonUtils.js';

		let camera, scene, renderer;
		let clock;

		const mixers = [];

		init();
		animate();

		function init() {

			camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 1, 1000);
			camera.position.set(2, 3, - 6);
			camera.lookAt(0, 1, 0);

			clock = new THREE.Clock();

			scene = new THREE.Scene();
			scene.background = new THREE.Color(0xa0a0a0);
			scene.fog = new THREE.Fog(0xa0a0a0, 10, 50);

			const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444);
			hemiLight.position.set(0, 20, 0);
			scene.add(hemiLight);

			const dirLight = new THREE.DirectionalLight(0xffffff);
			dirLight.position.set(- 3, 10, - 10);
			dirLight.castShadow = true;
			dirLight.shadow.camera.top = 4;
			dirLight.shadow.camera.bottom = - 4;
			dirLight.shadow.camera.left = - 4;
			dirLight.shadow.camera.right = 4;
			dirLight.shadow.camera.near = 0.1;
			dirLight.shadow.camera.far = 40;
			scene.add(dirLight);

			scene.add( new THREE.CameraHelper( dirLight.shadow.camera ) );

			// ground
			const mesh = new THREE.Mesh(new THREE.PlaneGeometry(200, 200), new THREE.MeshPhongMaterial({ color: 0x999999, depthWrite: false }));
			mesh.rotation.x = - Math.PI / 2;
			mesh.receiveShadow = true;
			scene.add(mesh);

			const loader = new GLTFLoader();
			loader.load('../three.js-r151/examples/models/gltf/Soldier.glb', function (gltf) {
				gltf.scene.traverse(function (object) {
					if (object.isMesh) object.castShadow = true;
				});

				const model1 = SkeletonUtils.clone(gltf.scene);
				const model2 = SkeletonUtils.clone(gltf.scene);
				const model3 = SkeletonUtils.clone(gltf.scene);
				const model4 = SkeletonUtils.clone(gltf.scene);

				const mixer1 = new THREE.AnimationMixer(model1);
				const mixer2 = new THREE.AnimationMixer(model2);
				const mixer3 = new THREE.AnimationMixer(model3);

				mixer1.clipAction(gltf.animations[0]).play(); // idle
				mixer2.clipAction(gltf.animations[1]).play(); // run
				mixer3.clipAction(gltf.animations[3]).play(); // walk

				model1.position.x = - 2;
				model2.position.x = 0;
				model3.position.x = 2;
				model4.position.x = 1;
				model4.position.z = 2;

				scene.add(model1, model2, model3, model4);
				mixers.push(mixer1, mixer2, mixer3);
			});

			renderer = new THREE.WebGLRenderer({ antialias: true });
			renderer.setPixelRatio(window.devicePixelRatio);
			renderer.setSize(window.innerWidth, window.innerHeight);
			renderer.outputEncoding = THREE.sRGBEncoding;
			renderer.shadowMap.enabled = true;
			document.body.appendChild(renderer.domElement);
			// 鼠标旋转控制
			const controls = new OrbitControls(camera, document.body);
			window.addEventListener('resize', onWindowResize);

			// 坐标系
			const axesHelper = new THREE.AxesHelper(10);
			scene.add(axesHelper);
		}

		function onWindowResize() {
			camera.aspect = window.innerWidth / window.innerHeight;
			camera.updateProjectionMatrix();
			renderer.setSize(window.innerWidth, window.innerHeight);
		}

		function animate() {
			requestAnimationFrame(animate);

			const delta = clock.getDelta();
			for (const mixer of mixers) mixer.update(delta);
			renderer.render(scene, camera);
		}

	</script>

</body>

</html>